// $codepro.audit.disable
/**
 * @author Team Awesome Express
 * @version $ Revision 1.0 $
 */




import com.google.gdata.client.spreadsheet.SpreadsheetService;
import com.google.gdata.data.spreadsheet.CellEntry;
import com.google.gdata.data.spreadsheet.CellFeed;
import com.google.gdata.util.ServiceException;

import java.awt.BorderLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;

/**
 * Widget for displaying and editing a spreadsheet.
 *
 * This is just for demonstrative purposes, it is not very featureful.
 *
 * 
 * @author Marcus
 * @version $Revision: 1.0 $
 */
public class CellBasedSpreadsheetPanel extends JPanel {

  /** The underlying Google Spreadsheets service. */
  private SpreadsheetService service;

  /** The URL of the cell feed. */
  private URL cellFeedUrl;

  /**
   * Field model.
   */
  private SpreadsheetTableModel model;
  /**
   * Field table.
   */
  private JTable table;
  /**
   * Field refreshButton.
   */
  private JButton refreshButton;
  /**
   * Field userType.
   */
  private static int userType;
  /**
   * Field sheetType.
   */
  private static int sheetType;
  /**
   * Field TRCOL - Treatment Record Column
   */
  private final int TRCOL = 12; // $codepro.audit.disable numericLiterals
  /**
   * FIELD DOCOL - Doctors Orders Column
   */
  private final int DOCOL = 16;  // $codepro.audit.disable numericLiterals -->
  
  private final int USERCOL = 5;
  /**
   * Creates the cell-based spreadsheet widget.
   *
   * @param service the Google Spreadsheets service to connect to
   * @param cellFeedUrl the URL of the cell feed
   */
  public CellBasedSpreadsheetPanel(
      SpreadsheetService service, URL cellFeedUrl) {
    this.service = service;
    this.cellFeedUrl = cellFeedUrl;
    model = new SpreadsheetTableModel(-1);
    initializeGui();
  }
  
  /**
   * Constructor for CellBasedSpreadsheetPanel.
   * @param service SpreadsheetService
   * @param cellFeedUrl URL
   * @param userType int
   * @param sheetType int
   */
  public CellBasedSpreadsheetPanel(SpreadsheetService service, URL cellFeedUrl, int userType, int sheetType) { //$codepro.audit.disable lineLength
	    this.service = service;
	    this.cellFeedUrl = cellFeedUrl;
	    this.sheetType = sheetType;
	    model = new SpreadsheetTableModel(userType);
	    this.userType = userType;
	    initializeGui();
	  }


  /**
   * Sets a cell at the specified row and column.
   *
  
   * @param row int
   * @param col int
   * @param valueOrFormula String
   * @return the newly set cell, returned back from the server */
  private CellEntry actuallySetCell(int row, int col, String valueOrFormula) {
    try {
      // This method ignores collisions.  Use update() if you are afraid
      // of overwriting other users' data.
      CellEntry entry = new CellEntry(row, col, valueOrFormula);
      return service.insert(cellFeedUrl, entry);
    } catch (IOException ioe) {
  //    SpreadsheetApiDemo.showErrorBox(ioe); WHY IS THIS HERE? - Kevin
      return null;
    } catch (ServiceException se) {
    //  SpreadsheetApiDemo.showErrorBox(se); WHY IS THIS HERE? - Kevin
      return null;
    }
  }

  /**
   * Gets a list of all cells.
   *
   * This just calls the method getAllCells in cellFellFeedHelper.
  
   * @return CellFeed */
  private CellFeed getCellFeed() {
    try {
      return service.getFeed(cellFeedUrl, CellFeed.class);
    } catch (IOException ioe) {
 //     SpreadsheetApiDemo.showErrorBox(ioe);
      return null;
    } catch (ServiceException se) {
 //     SpreadsheetApiDemo.showErrorBox(se);
      return null;
    }
  }

  // -- Mostly GUI code from here on down --

  /**
   * The Swing model for the spreadsheet.
   *
   * This is mostly GUI code.
   * @author Marcus
   */
  private class SpreadsheetTableModel extends AbstractTableModel {

    /** All the cells indexed for easy display purposes. */
    private Map<Point, CellEntry> cells = new HashMap<Point, CellEntry>();

    /** The last row to display (1-based). */
    private int maxRow;

    /** The last column to display (1-based). */
    private int maxCol;


    /**
     * Constructor for SpreadsheetTableModel.
     * @param userType int
     */
    private SpreadsheetTableModel(int userType) {
      refresh(userType);
    }


    /**
     * Load all the cells from Google Spreadsheets.
     * @param userType int
     */
    public synchronized void refresh(int userType) {
      cells.clear();

      CellFeed cellFeed = getCellFeed();

      if (cellFeed != null) {
        for (CellEntry entry : cellFeed.getEntries()) {
          doAddCell(entry);
        }
      }

      int oldMaxRow = maxRow;
      int oldMaxCol = maxCol;
      
//      if (userType == GlobalVars.NURSE_USERTYPE) { // Usertype is a nurse
//    	  switch (sheetType){
//    	  case GlobalVars.PATIENT_SHEET: // This is true if the edit patients button is pressed
//    		  maxCol = TRCOL; 
//    		  break;
//    	  case GlobalVars.TREATMENT_RECORD_SHEET:
//    		  /*
//    		   * can only edit treatment up until columm 12, 13 
//    		   * checks if has doctors orders, 14 starts doctors orders
//    		   */
//    		  maxCol = TRCOL;  
//    		  break;
//    	  case GlobalVars.USER_SHEET:
//    		  
//    		  maxCol = USERCOL; // 5 Columns
//    		  break;
//    	  }
//      } // end usertype nurse
//      else if (userType == GlobalVars.DOCTOR_USERTYPE) { // Usertype is a nurse
//    	  switch (sheetType){
//    	  case GlobalVars.PATIENT_SHEET: // This is true if the edit patients button is pressed
//    		  maxCol = TRCOL; 
//    		  break;
//    	  case GlobalVars.TREATMENT_RECORD_SHEET:
//    		  maxCol = DOCOL; 
//    		  break;
//    	  }
//      } // end usertype doctor
//      
//      else if (userType == GlobalVars.ADMIN_USERTYPE) {
//    	  switch (sheetType){
//    	  case GlobalVars.USER_SHEET:
//    		  maxCol = 5; // Can't add doctors orders to treatment record 
//    		  break;
//    	  }
//    	  }
//      
      
//      else {
    	  maxRow = cellFeed.getRowCount(); // $codepro.audit.disable
          maxCol = cellFeed.getColCount();
//      }
      maxRow = cellFeed.getRowCount();
      fireTableDataChanged();

      if (maxRow != oldMaxRow || maxCol != oldMaxCol) {
        fireTableStructureChanged();
      }
    }

    /**
     * Implements the Swing method for handling cell edits.
     * @param value Object
     * @param screenRow int
     * @param screenCol int
    
     * @see javax.swing.table.TableModel#setValueAt(Object, int, int) */
    public void setValueAt(Object value, int screenRow, int screenCol) {
      int row = screenRow + 1; // account for the fact Swing is 0-indexed
      int col = screenCol + 1;
      


      CellEntry entry = actuallySetCell(row, col, value.toString());

      if (entry != null) {
        doAddCell(entry);
      }

      fireTableDataChanged();
    }

    /** Tells Swing how many rows are in this table. * @return int
    
     * @return maxRow two rows that the user can insert to.
     * @return int
     * @see javax.swing.table.TableModel#getRowCount() */
    public int getRowCount() {
      return maxRow; // Allow user to insert up to two rows
    }

    /** Tells Swing how many columns are in this table. * @return int
    
     * @return maxCol number of columns that the user can insert to
     * @return int
     * @see javax.swing.table.TableModel#getColumnCount() */
    public int getColumnCount() {
      return maxCol;
    }

    /** Gets the cached version of the specified cell. * @param row int
     * @param col
     * @param row
    
     * @param row int
     * @param col int
     * @return CellEntry */
    public CellEntry getCell(int row, int col) {
      return cells.get(new Point(row, col));
    }

    /** Tells Swing the value at a particular location. * @param screenRow int
     * @param screenCol
     * @param screenRow
    
    
     * @param screenRow int
     * @param screenCol int
     * @return Object * @see javax.swing.table.TableModel#getValueAt(int, int) */
    public Object getValueAt(int screenRow, int screenCol) {
      CellEntry cell = getCell(screenRow + 1, screenCol + 1);
      if (cell == null) {
        return null;
      } else {
        return cell.getCell().getValue();
      }
    }

    /**
     * Method addCell.
     * @param entry CellEntry
     */
    public void addCell(CellEntry entry) {
      doAddCell(entry);
    }


    /**
     * Method doAddCell.
     * @param entry CellEntry
     */
    private void doAddCell(CellEntry entry) {
      int row = entry.getCell().getRow();
      int col = entry.getCell().getCol();

      cells.put(new Point(row, col), entry);
    }

    /** Tells Swing whether the cell is editable. * @param screenRow int
     * @param screenCol
     * @param screenRow
    
    
     * @param screenRow int
     * @param screenCol int
     * @return boolean * @see javax.swing.table.TableModel#isCellEditable(int, int) */
    public boolean isCellEditable(int screenRow, int screenCol) {
      CellEntry cell = getCell(screenRow + 1, screenCol + 1);

      if (cell == null) {
        // Although this can be wrong, assume editable unless told otherwise.
        return true;
      } else {
        return cell.getEditLink() != null;
      }
    }
  }

  /**
   * Method createWindow.
   * @param service SpreadsheetService
   * @param cellFeedUrl URL
  
   * @return JFrame */
  public static JFrame createWindow(
      SpreadsheetService service, URL cellFeedUrl) {
    JFrame frame = new JFrame();
    frame.setSize(600, 480); // $codepro.audit.disable numericLiterals
    frame.getContentPane().add(new CellBasedSpreadsheetPanel(service, cellFeedUrl, userType, sheetType)); //$codepro.audit.disable lineLength
    frame.setVisible(true);
    frame.setTitle("User List");
    return frame;
  }

  /**
   * Method initializeGui.
   */
  private void initializeGui() {
    table = new JTable(model);
    table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
    JScrollPane scrollpane = new JScrollPane(table);
    setLayout(new BorderLayout());
    add(scrollpane, BorderLayout.CENTER);
    refreshButton = new JButton("Refresh");
    refreshButton.addActionListener(new ActionHandler());
    add(refreshButton, BorderLayout.SOUTH);
  }

  /**
   * @author Marcus
   */
  private class ActionHandler implements ActionListener {
    /**
     * Method actionPerformed.
     * @param ae ActionEvent
    
     * @see java.awt.event.ActionListener#actionPerformed(ActionEvent) */
    public void actionPerformed(ActionEvent ae) {
      if (ae.getSource().equals(refreshButton)) {
       // model.refresh();
      }
    }
  }
}
